package net.tv90.volunteerserveradmin.aop;

import cn.dev33.satoken.exception.DisableServiceException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import lombok.extern.slf4j.Slf4j;
import net.tv90.volunteerserveradmin.exception.ServiceException;
import net.tv90.volunteerserveradmin.utils.entity.Result;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Objects;

@Slf4j
@RestControllerAdvice(annotations = RestController.class)
public class GlobalExceptionHandler {

    /**
     * 处理用户未登录
     */
    @ExceptionHandler(NotLoginException.class)
    public Result<Void> handleNotLoginException(NotLoginException ex) {
        String message;
        if (ex.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "未提供token";
        } else if (ex.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "token无效";
        } else if (ex.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "token已过期";
        } else {
            message = "当前会话未登录";
        }
        return Result.failed(message);
    }

    /**
     * 处理用户没有对应权限
     */
    @ExceptionHandler(NotPermissionException.class)
    public Result<Void> handleNotPermissionException(NotPermissionException ex) {
        return Result.failed("用户没有对应权限");
    }

    /**
     * 处理用户没有对应角色权限
     */
    @ExceptionHandler(NotRoleException.class)
    public Result<Void> handleNotRoleException(NotRoleException ex) {
        return Result.failed("用户没有对应角色权限");
    }

    /**
     * 处理账号封禁
     */
    @ExceptionHandler(DisableServiceException.class)
    public Result<Void> handleDisableServiceExceptionException() {
        return Result.failed("此账号已被禁止访问服务");
    }

    /**
     * 处理业务异常
     */
    @ExceptionHandler(ServiceException.class)
    public Result<Void> handleServiceException(ServiceException e) {
        return Result.failed(e.getMessage());
    }

    /**
     * 处理Assert异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public Result<Void> handleIllegalArgumentException(IllegalArgumentException e) {
        return Result.failed(e.getMessage());
    }

    /**
     * 处理参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return Result.failed(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    /**
     * 处理系统异常
     */
    @ExceptionHandler(Exception.class)
    public Result<Void> handleSystemException(Exception e) {
        e.printStackTrace();
        return Result.failed(stackTraceToString(e, 2000));
    }


    public String stackTraceToString(Exception exception, int maxCharCount) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(exception.getClass().getName()) // 异常类名
                .append(": ")
                .append(exception.getMessage()) // 异常信息
                .append("\n");
        // 遍历堆栈信息
        for (StackTraceElement element : exception.getStackTrace()) {
            stringBuilder.append("\tat ").append(element).append("\n");
        }
        // 截取字符
        String result = stringBuilder.toString();
        return result.length() > maxCharCount ? result.substring(0, maxCharCount) : result;
    }

}